using System;
using System.Globalization;
using System.IO;
using System.Collections;
using System.Security.Permissions;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
#if !PocketPC || DesignTime
using System.ComponentModel;
using System.Runtime.Serialization;
#endif
using System.Reflection;

namespace GeoFramework
{

	/// <summary>Represents a coordinate system based on interpretations of the Earth's shape and size.</summary>
	/// <remarks>
	/// 	<para>Over the course of history, advances in technology have given people the
	///     ability to more accurately measure the shape and size of the Earth. Since countries
	///     have built significant infrastructure based upon older coordinate systems, they
	///     cannot immediately abandon them in favor of new ones. As a result, there are now
	///     over fifty interpretations of Earth's shape and size in use all over the
	///     world.</para>
	/// 	<para>Some datums, such as World Geodetic System 1984 (or WGS84 for short) are
	///     becoming more widely used throughout the world, and this datum is used by nearly
	///     all GPS devices. However, while the world is slowly standardizing its datums, some
	///     datums will not be abandoned because they remain quite accurate for a specific,
	///     local area.</para>
	/// 	<para>A datum on its own is nothing more than a more granular interpretation of an
	///     ellipsoid. Typically, more specific coordinate transformation information is
	///     further associated with a datum to produce meaningful information. For example,
	///     Helmert and Molodensky coordinate conversion formulas use several local conversion
	///     parameters for each datum.</para>
	/// 	<para>Instances of this class are guaranteed to be thread-safe because the class is
	///     immutable (its properties can only be set via constructors).</para>
	/// </remarks>
	/// <seealso cref="Ellipsoid">Ellipsoid Class</seealso>
#if !PocketPC || DesignTime
#if Framework20
    [Obfuscation(Feature = "renaming", Exclude = false, ApplyToMembers = true)]
    [Obfuscation(Feature = "controlflow", Exclude = true, ApplyToMembers = true)]
    [Obfuscation(Feature = "stringencryption", Exclude = false, ApplyToMembers = true)]
#endif
	[TypeConverter(typeof(ExpandableObjectConverter))]
	[Serializable()]
    [ImmutableObject(true)]
#endif
#if Framework20
    [XmlSchemaProvider("GetXmlSchema")]
#endif
    public sealed class Datum : IFormattable
#if !PocketPC || (PocketPC && Framework20)
		, IXmlSerializable
#endif 
#if !PocketPC || DesignTime
        , ISerializable
#endif
	{

        private static readonly ArrayList pDatums = new ArrayList(16);

        #region Private Variables

        private Ellipsoid pEllipsoid;
		private string pName;

        #endregion

        #region Constructors

        /// <summary>Creates a new instance using the specified name and reference ellipsoid.</summary>
		/// <param name="name">A <strong>String</strong> containing the user-friendly name for the 
		/// datum.</param>
		/// <param name="ellipsoid">
		/// An <strong>Ellipsoid</strong> describing the shape of the Earth, used as a basis
		/// for the datum.
		/// </param>
		public Datum(string name, Ellipsoid ellipsoid)
		{
			pEllipsoid = ellipsoid;
			pName = name;

            // Add the datum to the collection
            pDatums.Add(this);
		}

#if !PocketPC || DesignTime
        /// <summary>
        /// Creates a new instance by de-serializing previously-serialized information.
        /// </summary>
        /// <param name="info">A <strong>SerializationInfo</strong> object containing serialized data.</param>
        /// <param name="context">A <strong>StreamingContext</strong> object describing the context of serialization.</param>
        /// <remarks>This constructor will de-serialize a previously-serialized object.  Objects are created
        /// serialized and de-serialized based on the "DecimalDegrees" value to maintain precision.</remarks>
        private Datum(SerializationInfo info, StreamingContext context)
        {
            pName = info.GetString("Name");
            pEllipsoid = (Ellipsoid)info.GetValue("Ellipsoid", typeof(Ellipsoid));

            // Add the datum to the collection
            pDatums.Add(this);
        }
#endif

        #endregion

        #region Static Variables

        /// <summary>
        /// Returns the entire collection of known datums.
        /// </summary>
        public static ArrayList Datums
        {
            get
            {
                return pDatums;
            }
        }

        /// <summary>Represents the Adindan datum.</summary>
		/// <remarks>This datum is used primarily in African countries.</remarks>
		public static readonly Datum Adindan = new Datum("Adindan", Ellipsoid.Clarke1880);
		/// <summary>Represents the Afgooye datum.</summary>
		/// <remarks>This datum is used primarily in Somalia and uses the Krassovsky ellipsoid of 1940.</remarks>
		public static readonly Datum Afgooye = new Datum("Afgooye", Ellipsoid.Krassovsky1940);
		/// <summary>Represents the Ain el Abd 1970 datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum AinelAbd1970 = new Datum("Ain el Abd 1970", Ellipsoid.International1924);
		/// <summary>Represents the American Samoa datum of 1962.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1866.</remarks>
		public static readonly Datum AmericanSamoa1962 = new Datum("American Samoa 1962", Ellipsoid.Clarke1866);
		/// <summary>Represents the Anna 1 Astro datum of 1965.</summary>
		public static readonly Datum Anna1Astro1965 = new Datum("Anna 1 Astro 1965", Ellipsoid.AustralianNational1965);
		/// <summary>Represents the Antigua Island Astro datum of 1943.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum AntiguaIslandAstro1943 = new Datum("Antigua Island Astro 1943", Ellipsoid.Clarke1880);
		/// <summary>Represents the Arc datum of 1950.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Arc1950 = new Datum("Arc 1950", Ellipsoid.Clarke1880);
		/// <summary>Represents the Arc datum of 1960.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Arc1960 = new Datum("Arc 1960", Ellipsoid.Clarke1880);
		/// <summary>Represents the Ascension Island datum of 1958.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum AscensionIsland1958 = new Datum("Ascension Island 1958", Ellipsoid.International1924);
		/// <summary>Represents the Astro Beacon "E" datum of 1945.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum AstroBeaconE1945 = new Datum("Astro Beacon \"E\" 1945", Ellipsoid.International1924);
		/// <summary>Represents the Astro DOS 71/4 datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum AstroDos714 = new Datum("Astro DOS 71/4", Ellipsoid.International1924);
		/// <summary>Represents the Astro Tern Island (Frig) datum of 1961.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum AstroTernIslandFrig1961 = new Datum("Astro Tern Island (Frig) 1961", Ellipsoid.International1924);
		/// <summary>Represents the Astronomical Station datum of 1952.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum AstronomicalStation1952 = new Datum("Astronomical Station 1952", Ellipsoid.International1924);
		/// <summary>Represents the Australian Geodetic datum of 1966.</summary>
		public static readonly Datum AustralianGeodetic1966 = new Datum("Australian Geodetic 1966", Ellipsoid.AustralianNational1965);
		/// <summary>Represents the Australian Geodetic datum of 1984.</summary>
		public static readonly Datum AustralianGeodetic1984 = new Datum("Australian Geodetic 1984", Ellipsoid.AustralianNational1965);
		/// <summary>Represents the Ayabelle Lighthouse datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum AyabelleLighthouse = new Datum("Ayabelle Lighthouse", Ellipsoid.Clarke1880);
		/// <summary>Represents the Bellevue (IGN) datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum BellevueIgn = new Datum("Bellevue (IGN)", Ellipsoid.International1924);
		/// <summary>Represents the Bermuda datum of 1957.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1866.</remarks>
		public static readonly Datum Bermuda1957 = new Datum("Bermuda 1957", Ellipsoid.Clarke1866);
		/// <summary>Represents the Bissau datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum Bissau = new Datum("Bissau", Ellipsoid.International1924);
		/// <summary>Represents the Bogota Observatory datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum BogotaObservatory = new Datum("Bogota Observatory", Ellipsoid.International1924);
		/// <summary>Represents the Bukit Rimpah datum.</summary>
		public static readonly Datum BukitRimpah = new Datum("Bukit Rimpah", Ellipsoid.Bessel1841);
		/// <summary>Represents the Camp Area Astro datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum CampAreaAstro = new Datum("Camp Area Astro", Ellipsoid.International1924);
		/// <summary>Represents the Campo Inchauspe datum of 1969.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum CampoInchauspe = new Datum("Campo Inchauspe 1969", Ellipsoid.International1924);
		/// <summary>Represents the Canton Astro datum of 1966.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum CantonAstro1966 = new Datum("Canton Astro 1966", Ellipsoid.International1924);
		/// <summary>Represents the Cape datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Cape = new Datum("Cape", Ellipsoid.Clarke1880);
		/// <summary>Represents the Cape Canaveral datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1866.</remarks>
		public static readonly Datum CapeCanaveral = new Datum("Cape Canaveral", Ellipsoid.Clarke1866);
		/// <summary>Represents the Carthage datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Carthage = new Datum("Carthage", Ellipsoid.Clarke1880);
		/// <summary>Represents the Chatham Island Astro datum of 1971.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum ChathamIslandAstro1971 = new Datum("Chatham Island Astro 1971", Ellipsoid.International1924);
		/// <summary>Represents the Chua Astro datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum ChuaAstro = new Datum("Chua Astro", Ellipsoid.International1924);
		/// <summary>Represents the CorregoAlegre datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum CorregoAlegre = new Datum("CorregoAlegre", Ellipsoid.International1924);
		/// <summary>Represents the Dabola datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Dabola = new Datum("Dabola", Ellipsoid.Clarke1880);
		/// <summary>Represents the Deception Island datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum DeceptionIsland = new Datum("Deception Island", Ellipsoid.Clarke1880);
		/// <summary>Represents the Djakarta (Batavia) datum.</summary>
		public static readonly Datum DjakartaBatavia = new Datum("Djakarta (Batavia)", Ellipsoid.Bessel1841);
		/// <summary>Represents the DOS datum of 1968.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum Dos1968 = new Datum("DOS 1968", Ellipsoid.International1924);
		/// <summary>Represents the Easter Island datum of 1967.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum EasterIsland1967 = new Datum("Easter Island 1967", Ellipsoid.International1924);
		/// <summary>Represents the Estonia Coordinate System datum of 1937.</summary>
		public static readonly Datum EstoniaLocalDatum1937 = new Datum("Estonia Coordinate System 1937", Ellipsoid.Bessel1841);
		/// <summary>Represents the European datum of 1950.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum European1950 = new Datum("European 1950", Ellipsoid.International1924);
		/// <summary>Represents the European datum of 1979.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum European1979 = new Datum("European 1979", Ellipsoid.International1924);
		/// <summary>Represents the Fort Thomas datum of 1955.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum FortThomas1955 = new Datum("Fort Thomas 1955", Ellipsoid.Clarke1880);
		/// <summary>Represents the GAN datum of 1970.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum Gan1970 = new Datum("GAN 1970", Ellipsoid.International1924);
		/// <summary>Represents the Geodetic Datum of 1949.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum GeodeticDatum1949 = new Datum("Geodetic Datum 1949", Ellipsoid.International1924);
		/// <summary>Represents the Graciosa Base SW datum of 1948.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum GraciosaBaseSW1948 = new Datum("Graciosa Base SW 1948", Ellipsoid.International1924);
		/// <summary>Represents the Guam 1963 datum.</summary>
		public static readonly Datum Guam1963 = new Datum("Guam 1963", Ellipsoid.Clarke1866);
		/// <summary>Represents the Gunung Segara datum.</summary>
		public static readonly Datum GunungSegara = new Datum("Gunung Segara", Ellipsoid.Bessel1841);
		/// <summary>Represents the GUX 1 Astro datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum Gux1Astro = new Datum("GUX 1 Astro", Ellipsoid.International1924);
		/// <summary>Represents the Herat North datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum HeratNorth = new Datum("Herat North", Ellipsoid.International1924);
		/// <summary>Represents the Hermannskogel datum.</summary>
		public static readonly Datum HermannskogelDatum = new Datum("Hermannskogel", Ellipsoid.Bessel1841Namibia);
		/// <summary>Represents the Hjorsey datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum Hjorsey1955 = new Datum("Hjorsey 1955", Ellipsoid.International1924);
		/// <summary>Represents the Hong Kong datum of 1963.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum HongKong1963 = new Datum("Hong Kong 1963", Ellipsoid.International1924);
		/// <summary>Represents the Hu-Tzu-Shan datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum HuTzuShan = new Datum("Hu-Tzu-Shan", Ellipsoid.International1924);
		/// <summary>Represents the Indian datum.</summary>
		public static readonly Datum Indian = new Datum("Indian", Ellipsoid.EverestIndia1830);
		/// <summary>Represents the Indian datum of 1954.</summary>
		public static readonly Datum Indian1954 = new Datum("Indian 1954", Ellipsoid.EverestIndia1830);
		/// <summary>Represents the Indian datum of 1960.</summary>
		public static readonly Datum Indian1960 = new Datum("Indian 1960", Ellipsoid.EverestIndia1830);
		/// <summary>Represents the Indian datum of 1975.</summary>
		public static readonly Datum Indian1975 = new Datum("Indian 1975", Ellipsoid.EverestIndia1830);
		/// <summary>Represents the Indonesian datum of 1974.</summary>
		public static readonly Datum Indonesian1974 = new Datum("Indonesian 1974", Ellipsoid.Indonesian1974);
		/// <summary>Represents the Ireland datum of 1965.</summary>
		public static readonly Datum Ireland1965 = new Datum("Ireland 1965", Ellipsoid.ModifiedAiry);
		/// <summary>Represents the ISTS 061 Astro datum of 1968.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum Ists061Astro1968 = new Datum("ISTS 061 Astro 1968", Ellipsoid.International1924);
		/// <summary>Represents the ISTS 073 Astro datum of 1969.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum Ists073Astro1969 = new Datum("ISTS 073 Astro 1969", Ellipsoid.International1924);
		/// <summary>Represents the Johnston Island datum of 1961.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum JohnstonIsland1961 = new Datum("Johnston Island 1961", Ellipsoid.International1924);
		/// <summary>Represents the Kandawala datum.</summary>
		public static readonly Datum Kandawala = new Datum("Kandawala", Ellipsoid.EverestIndia1830);
		/// <summary>Represents the Kerguelen Island datum of 1949.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum KerguelenIsland1949 = new Datum("Kerguelen Island 1949", Ellipsoid.International1924);
		/// <summary>Represents the Kertau datum of 1948.</summary>
		public static readonly Datum Kertau1948 = new Datum("Kertau 1948", Ellipsoid.Everest1948);
		/// <summary>Represents the Kusaie Astro datum of 1951.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum KusaieAstro1951 = new Datum("Kusaie Astro 1951", Ellipsoid.International1924);
		/// <summary>Represents the L. C. 5 Astro datum of 1961.</summary>
		public static readonly Datum LC5Astro1961 = new Datum("L. C. 5 Astro 1961", Ellipsoid.Clarke1866);
		/// <summary>Represents the Leigon datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Leigon = new Datum("Leigon", Ellipsoid.Clarke1880);
		/// <summary>Represents the Liberia datum of 1964.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Liberia1964 = new Datum("Liberia 1964", Ellipsoid.Clarke1880);
		/// <summary>Represents the Luzon datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1866.</remarks>
		public static readonly Datum Luzon = new Datum("Luzon", Ellipsoid.Clarke1866);
		/// <summary>Represents the M'Poraloko datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum MPoraloko = new Datum("M'Poraloko", Ellipsoid.Clarke1880);
		/// <summary>Represents the Mahe datum of 1971.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Mahe1971 = new Datum("Mahe 1971", Ellipsoid.Clarke1880);
		/// <summary>Represents the Massawa datum.</summary>
		public static readonly Datum Massawa = new Datum("Massawa", Ellipsoid.Bessel1841);
		/// <summary>Represents the Merchich datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Merchich = new Datum("Merchich", Ellipsoid.Clarke1880);
		/// <summary>Represents the Midway Astro datum of 1961.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum MidwayAstro1961 = new Datum("Midway Astro 1961", Ellipsoid.International1924);
		/// <summary>Represents the Minna datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Minna = new Datum("Minna", Ellipsoid.Clarke1880);
		/// <summary>Represents the Montserrat Island Astro datum of 1958.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum MontserratIslandAstro1958 = new Datum("Montserrat Island Astro 1958", Ellipsoid.Clarke1880);
		/// <summary>Represents the Nahrwan datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Nahrwan = new Datum("Nahrwan", Ellipsoid.Clarke1880);
		/// <summary>Represents the Naparima, BWI datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum NaparimaBwi = new Datum("Naparima, BWI", Ellipsoid.International1924);
		/// <summary>Represents the North American 1927 (NAD27) datum.</summary>
		public static readonly Datum NorthAmerican1927 = new Datum("North American 1927", Ellipsoid.Clarke1866);
		/// <summary>Represents the North American 1983 (NAD83) datum.</summary>
		public static readonly Datum NorthAmerican1983 = new Datum("North American 1983", Ellipsoid.Grs80);
		/// <summary>Represents the North Sahara datum of 1959.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum NorthSahara1959 = new Datum("North Sahara 1959", Ellipsoid.Clarke1880);
		/// <summary>Represents the Observatorio Meteorologico datum of 1939.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum ObservatorioMeteorologico1939 = new Datum("Observatorio Meteorologico 1939", Ellipsoid.International1924);
		/// <summary>Represents the Old Egyptian datum of 1907.</summary>
		public static readonly Datum OldEgyptian1907 = new Datum("Old Egyptian 1907", Ellipsoid.Helmert1906);
		/// <summary>Represents the Old Hawaiian datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1866.</remarks>
		public static readonly Datum OldHawaiian = new Datum("Old Hawaiian", Ellipsoid.Clarke1866);
		/// <summary>Represents the Oman datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Oman = new Datum("Oman", Ellipsoid.Clarke1880);
		/// <summary>Represents the Ordnance Survey of Great Britain datum of 1936.</summary>
		public static readonly Datum OrdnanceSurveyGreatBritain1936 = new Datum("Ordnance Survey of Great Britain 1936", Ellipsoid.Airy1830);
		/// <summary>Represents the Pico de las Nieves datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum PicodelasNieves = new Datum("Pico de las Nieves", Ellipsoid.International1924);
		/// <summary>Represents the Pitcairn Astro datum of 1967.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum PitcairnAstro1967 = new Datum("Pitcairn Astro 1967", Ellipsoid.International1924);
		/// <summary>Represents the Point 58 datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Point58 = new Datum("Point 58", Ellipsoid.Clarke1880);
		/// <summary>Represents the Pointe Noire datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum PointeNoire1948 = new Datum("Pointe Noire 1948", Ellipsoid.Clarke1880);
		/// <summary>Represents the Porto Santo datum of 1936.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum PortoSanto1936 = new Datum("Porto Santo 1936", Ellipsoid.International1924);
		/// <summary>Represents the Provisional South American datum of 1956.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum ProvisionalSouthAmerican1956 = new Datum("Provisional South American 1956", Ellipsoid.International1924);
		/// <summary>Represents the Provisional South Chilean datum of 1963.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum ProvisionalSouthChilean1963 = new Datum("Provisional South Chilean 1963", Ellipsoid.International1924);
		/// <summary>Represents the Puerto Rico datum.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1866.</remarks>
		public static readonly Datum PuertoRico = new Datum("Puerto Rico", Ellipsoid.Clarke1866);
		/// <summary>Represents the S-42 (Pulkovo 1942) datum.</summary>
		public static readonly Datum S42Pulkovo1942 = new Datum("S-42 (Pulkovo 1942)", Ellipsoid.Krassovsky1940);
		/// <summary>Represents the Qatar National datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum QatarNational = new Datum("Qatar National", Ellipsoid.International1924);
		/// <summary>Represents the Qornoq datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum Qornoq = new Datum("Qornoq", Ellipsoid.International1924);
		/// <summary>Represents the Reunion datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum Reunion = new Datum("Reunion", Ellipsoid.International1924);
		/// <summary>Represents the Rome datum of 1940.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum Rome1940 = new Datum("Rome 1940", Ellipsoid.International1924);
		/// <summary>Represents the S-JTSK datum.</summary>
		public static readonly Datum Sjtsk = new Datum("S-JTSK", Ellipsoid.Bessel1841);
		/// <summary>Represents the Santo (DOS) datum of 1965.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum SantoDos1965 = new Datum("Santo (DOS) 1965", Ellipsoid.International1924);
		/// <summary>Represents the Sao Braz datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum SaoBraz = new Datum("Sao Braz", Ellipsoid.International1924);
		/// <summary>Represents the Sapper Hill datum of 1943.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum SapperHill1943 = new Datum("Sapper Hill 1943", Ellipsoid.International1924);
		/// <summary>Represents the Schwarzeck datum.</summary>
		public static readonly Datum Schwarzeck = new Datum("Schwarzeck", Ellipsoid.Bessel1841Namibia);
		/// <summary>Represents the Selvagem Grande datum of 1938.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum SelvagemGrande1938 = new Datum("Selvagem Grande 1938", Ellipsoid.International1924);
		/// <summary>Represents the Sierra Leone datum of 1960.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum SierraLeone1960 = new Datum("Sierra Leone 1960", Ellipsoid.Clarke1880);
		/// <summary>Represents the South American datum of 1969.</summary>
		public static readonly Datum SouthAmerican1969 = new Datum("South American 1969", Ellipsoid.SouthAmerican1969);
		/// <summary>Represents the South Asia datum.</summary>
		public static readonly Datum SouthAsia = new Datum("South Asia", Ellipsoid.ModifiedFischer1960);
		/// <summary>Represents the Tarnanarive Observatory datum of 1925.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum TananariveObservatory1925 = new Datum("Tarnanarive Observatory 1925", Ellipsoid.International1924);
		/// <summary>Represents the Timbalai datum of 1948.</summary>
		public static readonly Datum Timbalai1948 = new Datum("Timbalai 1948", Ellipsoid.Everest);
		/// <summary>Represents the Tokyo datum.</summary>
		public static readonly Datum Tokyo = new Datum("Tokyo", Ellipsoid.Bessel1841);
		/// <summary>Represents the Tristan Astro datum of 1968.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum TristanAstro1968 = new Datum("Tristan Astro 1968", Ellipsoid.International1924);
		/// <summary>Represents the Viti Levu datum of 1916.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum VitiLevu1916 = new Datum("Viti Levu 1916", Ellipsoid.Clarke1880);
		/// <summary>Represents the Voirol datum of 1960.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Voirol1960= new Datum("Voirol 1960", Ellipsoid.Clarke1880);
		/// <summary>Represents the Voirol datum of 1880.</summary>
		/// <remarks>This datum uses the Clarke ellipsoid of 1880.</remarks>
		public static readonly Datum Voirol1874 = new Datum("Voirol 1874", Ellipsoid.Clarke1880);
		/// <summary>Represents the Wake Island Astro datum of 1952.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum WakeIslandAstro1952 = new Datum("Wake Island Astro 1952", Ellipsoid.International1924);
		/// <summary>Represents the Wake Eniwetok datum of 1960.</summary>
		public static readonly Datum WakeEniwetok1960 = new Datum("Wake Eniwetok 1960", Ellipsoid.Hough1960);
		/// <summary>Represents the World Geodetic System datum of 1972.</summary>
		/// <remarks>This datum uses the World Geodetic System ellipsoid of 1972.</remarks>
		public static readonly Datum Wgs1972 = new Datum("WGS 1972", Ellipsoid.Wgs1972);
		/// <summary>Represents the World Geodetic System datum of 1984.</summary>
		/// <remarks>
		/// This datum is probably the most frequently used datum in the world. It is the
		/// datum used by almost all GPS devices for transmitting coordinate information.
		/// This datum uses the World Geodetic System ellipsoid of 1984.
		/// </remarks>
		public static readonly Datum Wgs1984 = new Datum("WGS 1984", Ellipsoid.Wgs1984);
		/// <summary>Represents the datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum Yacare = new Datum("Yacare", Ellipsoid.International1924);
		/// <summary>Represents the datum.</summary>
		/// <remarks>This datum uses the International ellipsoid of 1924.</remarks>
		public static readonly Datum Zanderij = new Datum("Zanderij", Ellipsoid.International1924);
		/// <summary>Represents the default datum used by the GeoFramework, WGS1984.</summary>
		public static readonly Datum Default = Datum.Wgs1984;

		#endregion

        /// <summary>
        /// Returns the name of the datum.
        /// </summary>
        public string Name
        {
            get
            {
                return pName;
            }
        }

		/// <summary>Returns the interpretation of Earth's shape associated with a datum.</summary>
		/// <value>
		/// Read only. An
		/// <see cref="Ellipsoid">Ellipsoid</see>
		/// object.
		/// </value>
		/// <remarks>Each datum is associated with an ellipsoid, which is an interpretation of Earth's shape and 
		/// size.</remarks>
		/// <example>
		///     This example gets information on the ellipsoid associated with the WGS84 datum. 
		///     <code lang="VB">
		/// ' Get information about the NAD1983 datum
		/// Dim MyDatum As Datum = Geodesy.GetDatum(DatumType.NorthAmerican1983)
		/// ' Get the ellipsoid associated with this datum
		/// Dim MyEllipsoid As Ellipsoid = MyDatum.Ellipsoid
		/// ' Write the semi-major axis of the ellipsoid
		/// Debug.WriteLine(MyEllipsoid.SemiMajorAxis.ToString())
		///     </code>
		/// 	<code lang="CS">
		/// // Get information about the NAD1983 datum
		/// Datum MyDatum = Geodesy.GetDatum(DatumType.NorthAmerican1983);
		/// // Get the ellipsoid associated with this datum
		/// Ellipsoid MyEllipsoid = MyDatum.Ellipsoid;
		/// // Write the semi-major axis of the ellipsoid
		/// Debug.WriteLine(MyEllipsoid.SemiMajorAxis.ToString());
		///     </code>
		/// </example>
		/// <seealso cref="Ellipsoid">Ellipsoid Class</seealso>
		public Ellipsoid Ellipsoid
		{
			get
			{
				return pEllipsoid;
			}
		}

        /// <summary>
        /// Returns a Datum object matching the specified name.
        /// </summary>
        /// <param name="datumName">A <strong>String</strong> describing the name of an existing datum.</param>
        /// <returns>A <strong>Datum</strong> object matching the specified string, or null if no datum was found.</returns>
        public static Datum FromName(string name)
        {
            foreach (Datum item in pDatums)
            {
                if (item.Name == name)
                    return item;
            }
            return null;
        }

		/// <summary>
		/// Compares the current instance to the specified datum object.
		/// </summary>
		public bool Equals(Datum value)
        {
#if !PocketPC || Framework20
            if (object.ReferenceEquals(value, null))
				return false;
#endif
			return GetHashCode().Equals(value.GetHashCode());
		}

		public override int GetHashCode()
		{
			return pEllipsoid.GetHashCode() ^ pName.GetHashCode();
		}

		#region IFormattable Members

		public override string ToString()
		{
			return pName;
		}

		string IFormattable.ToString(string format, IFormatProvider formatProvider)
		{
			return ToString();
		}

		#endregion

#if !PocketPC || (PocketPC && Framework20)
		#region IXmlSerializable Members

#if Framework20
        public static XmlQualifiedName GetXmlSchema(XmlSchemaSet xs)
        {
            // Load it from a string
            xs.Add(Xml.SchemaSet);

            // And return the type
            return new XmlQualifiedName("Datum", Xml.Namespace);
        }
#endif

        XmlSchema IXmlSerializable.GetSchema()
        {
            return null;
        }

        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            ReadXml(reader);
        }

        void IXmlSerializable.WriteXml(XmlWriter writer)
        {
            WriteXml(writer);
        }

        /// <summary>
        /// Populates the current instance by reading XML from the specified reader.
        /// </summary>
        /// <param name="reader"></param>
        public void ReadXml(XmlReader reader)
        {
            if (reader == null)
                throw new ArgumentNullException("reader");

            // Read in the name
            reader.MoveToAttribute("Name", Xml.Namespace);
            pName = reader.Value;

            // Now read in the elements
            while (!reader.EOF)
            {
                // Keep reading until we reach an element
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        switch (reader.Name)
                        {
                            case "Ellipsoid":
                                XmlSerializer EllipsoidSerializer = new XmlSerializer(typeof(Ellipsoid));
                                pEllipsoid = (Ellipsoid)EllipsoidSerializer.Deserialize(reader);
                                break;
                            default:
                                // Read the next item
                                reader.Read();
                                break;
                        }
                        break;
                    case XmlNodeType.EndElement:
                        if (String.Compare(reader.Name, "Datum", true, CultureInfo.InvariantCulture) == 0)
                        {
                            // Done reading!
                            return;
                        }
                        else
                        {
                            // Keep going
                            reader.Read();
                            continue;
                        }
                    default:
                        // Read the next item
                        reader.Read();
                        break;
                }
            }
        }

        /// <summary>
        /// Writes the values of the current instance to the specified XML writer.
        /// </summary>
        /// <param name="writer"></param>
        public void WriteXml(XmlWriter writer)
        {
            if (writer == null)
                throw new ArgumentNullException("writer");

            writer.WriteStartAttribute("Name", Xml.Namespace);
            writer.WriteString(pName);
            writer.WriteEndAttribute();

            // Defer to the Distance serializer for other stuff
            XmlSerializer x = new XmlSerializer(typeof(Ellipsoid));
            writer.WriteStartElement("Ellipsoid");
            x.Serialize(writer, pEllipsoid);
            writer.WriteEndElement();
        }

        #endregion
#endif

#if !PocketPC || DesignTime
        #region ISerializable Members

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]  
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Name", pName);
            info.AddValue("Ellipsoid", pEllipsoid);
        }

        #endregion
#endif
	}

}